using System;
using System.Collections.Generic;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using DslCrossModelFramework.ModelRelationship;
using DslCrossModelFramework.ModelTraversal;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Design;

namespace DslCrossModelFramework.UI {
    public class ModelBrowserDropDownTypeEditor : UITypeEditor {
        
        #region UITypeEditor Implementation
        /// <summary>
        /// Overridden to specify that our editor is a modal form
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context) {
            return UITypeEditorEditStyle.Modal;
        }



        /// <summary>
        /// Called by VS whenever the user clicks on the ellipsis in the 
        /// properties window for a property to which this editor is linked.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="provider"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public sealed override object EditValue(
            System.ComponentModel.ITypeDescriptorContext context,
            IServiceProvider provider,
            object value) {
            if (provider == null) {
                throw new ArgumentNullException("provider");
            }
            if (context == null) {
                throw new ArgumentNullException("context");
            }


            // Get a reference to the underlying property element
            typeDescriptor = context.PropertyDescriptor as ElementPropertyDescriptor;

            ModelElement underlyingModelElement = typeDescriptor.ModelElement;

            // context.Instance also returns a model element, but this will either
            // be the shape representing the underlying element (if you selected
            // the element via the design surface), or the underlying element 
            // itself (if you selected the element via the model explorer)
            //ModelElement element = context.Instance as ModelElement;

            // Create an instance of the windows forms editor
            service =
                (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));





            manager = new CrossModelManager(underlyingModelElement.Store);

            this.currentValue = value;
            ModelPath currentPath = null;
            if (value is ModelPath) {
                currentPath = value as ModelPath;
            }
            else if (value is string) {
                string strValue = (string)value;
                if (!string.IsNullOrEmpty(strValue)) {
                    currentPath = ModelPath.DeserializeFromString(strValue, manager);
                }
            }

            ModelElementTree control = new ModelElementTree(manager, GetModelRelationships, string.Empty, ModelSelectionMode.ModelPath, currentPath);
            ConfigureDropDown(control);
            control.Bind();

            control.SelectionChanged += new EventHandler<ModelItemSelectionEventArgs>(dialog_SelectionChanged);
            control.SelectNoneClicked += new EventHandler<EventArgs>(dialog_SelectNoneClicked);
            this.service.DropDownControl(control);

            return GetReturnValue(control);
           
        }

        private ModelPath selectedValue;

        void dialog_SelectNoneClicked(object sender, EventArgs e) {
            selectedValue = null;
            if (service != null) {
                service.CloseDropDown();
            }
        }

        void dialog_SelectionChanged(object sender, ModelItemSelectionEventArgs e) {
            selectedValue = e.SelectedModelPath;
            if (service != null) {
                service.CloseDropDown();
            }
        }

        private IWindowsFormsEditorService service;
        #endregion

        /// <summary>
        /// Configures the dialog.
        /// </summary>
        /// <param name="control">The tree control.</param>
        protected virtual void ConfigureDropDown(ModelElementTree control) {

        }


        /// <summary>
        /// Gets the return value.
        /// </summary>
        /// <param name="control">The dialog.</param>
        /// <returns></returns>
        protected virtual object GetReturnValue(ModelElementTree control) {
            return control.SelectedPath == null ? null : control.SelectedPath.SerializeToString();
        }


        /// <summary>
        /// Gets the manager.
        /// </summary>
        /// <value>The manager.</value>
        public CrossModelManager Manager {
            get { return manager; }
        }

        private CrossModelManager manager;


        private ElementPropertyDescriptor typeDescriptor;
        public ElementPropertyDescriptor TypeDescriptor {
            get { return typeDescriptor; }
        }


        private object currentValue;
        /// <summary>
        /// Gets the current value.
        /// </summary>
        /// <value>The current value.</value>
        public object CurrentValue {
            get { return currentValue; }
        }

        /// <summary>
        /// Gets the model relationships.
        /// </summary>
        /// <returns></returns>
        protected virtual IEnumerable<IModelRelationshipDefinition> GetModelRelationships(DomainClassInfo parent, string scope) {
            //List<IModelRelationshipDefinition> modelRelationships = new List<IModelRelationshipDefinition>();
            //foreach (Type melRootType in manager.GetModelDirectory().GetAllModelRootTypes()) {
            //    if (melRootType != null) {
            //        modelRelationships.Add(new DefaultModelRelationshipDefinition(melRootType));
            //    }
            //}

            //return modelRelationships;
            return ModelRelationshipManager.Current.GetRelationships(parent, scope);

        }
    }
    
}